import { Component, Input, Output, EventEmitter, ViewChild, OnInit, OnChanges, ElementRef, ChangeDetectorRef } from '@angular/core';
import { ColumnOptions } from './models/columnOptions.model';
import { TableOptions } from './models/tableOptions.model';
import { PageOptions } from './models/pageOptions.model';
import { ColumnHeader, ColumnOperation } from './models/columnHeader.model';
import { PaginationComponent } from './pagination/pagination.component';
import { Page } from './models/pagination.model';
import { FixedColumnPipe } from './fixedColumn.pipe';

/**
 * Table module
 *
 * Author: Andrei Istrate
 * Date: 25.04.2018
 */

export enum PaginationPositionDisplayEnum {
    Down = 0,
    Up = 1,
    UpAndDown = 2
}

@Component({
    selector: 'sustainalytics-table',
    templateUrl: './table.component.html',
    styleUrls: ['../../../../assets/table.scss', './table.component.scss'],
    providers: [FixedColumnPipe],
})
export class TableComponent implements OnChanges {
    public orderByAsc: boolean = true;
    public orderByCol: string;
    public activeColumn: string;
    public paginationObject: any;
    public checkPagination: any = PaginationPositionDisplayEnum;
    public sourceTransformed: any[];
    public currentPage: Page = new Page(0, 20);

    public fixedColumns: any[] = [];
    public dynamicColumns: any[] = [];

    private _columns: ColumnOptions[];

    public setCols(value: ColumnOptions[]){
        this._columns = value;
        this.fixedColumns = this.pipe.transform(this._columns, true);
        this.dynamicColumns = this.pipe.transform(this._columns, false);
    }

    @Input() set columns(value: ColumnOptions[]) {
        if (value) {
            this._columns = value;
            this.fixedColumns = this.pipe.transform(this._columns, true);
            this.dynamicColumns = this.pipe.transform(this._columns, false);
        }
    }

    @Input() source: any[];
    @Input() filter: any;
    @Input() elementCount: number;
    @Input() paginationStateChanged: { pageSize: number; pageIndex: number };
    @Input() paginationPositionDisplay: PaginationPositionDisplayEnum;
    @Input() canReorder: boolean;
    @Input() hasNonFixedCols: boolean;
    @Input() displayTitle = true;
    @Input() showPagination = true;
    @Input() rowHeight: number;
    @Input() set take(value: number){
        if(value){
            this.currentPage.take = value;
            this.paginationStateChanged = {
                pageSize: this.currentPage.take,
                pageIndex: (this.currentPage.skip / this.currentPage.take) + 1
            };
        }
    }

    @ViewChild('pagination') pagination: PaginationComponent;

    @Output() changed: EventEmitter<TableOptions> = new EventEmitter();

    @Output() buttonClicked: EventEmitter<any> = new EventEmitter();

    @Output() columnReorder: EventEmitter<string[]> = new EventEmitter();

    constructor(private pipe: FixedColumnPipe) { }  

    ngOnChanges() {
        if (this.source) {
            this.sourceTransformed = this.transformToArray(this.source);
        }
    }

    public pageChanged(page: Page): void {
        this.currentPage = page;
        this.emitTableOptionsChanged(true);
        this.paginationStateChanged = {
            pageSize: this.currentPage.take,
            pageIndex: (this.currentPage.skip / this.currentPage.take) + 1
        };
    }

    public doSomething(arg: ColumnHeader): void {
        this.activeColumn = arg.sortIdentifier;
        switch (arg.operation) {
            case ColumnOperation.search:
                {
                    this.filter[arg.searchIdentifier] = arg.value;
                    this.orderByAsc = true;
                    if (arg.value == '')
                        this.activeColumn = this._columns[0].searchIdentifier;
                    else
                        this.orderByCol = arg.sortIdentifier;

                    this.currentPage.skip = 0;
                    this.currentPage.take = 20;

                    this.emitTableOptionsChanged(false);
                    break;
                }
            case ColumnOperation.sort:
                {
                    this.orderByCol = arg.sortIdentifier;
                    this.orderByAsc = arg.value;

                    this.emitTableOptionsChanged(true);
                    break;
                }
        }
    }

    private emitTableOptionsChanged(listOnly: boolean): void {
        let pageOptions: PageOptions = new PageOptions(
            this.currentPage.skip,
            this.currentPage.take,
            listOnly
        );
        if (this.orderByCol == null) this.orderByCol = this._columns[0].sortIdentifier;
        if (this.activeColumn == null) this.activeColumn = this._columns[0].searchIdentifier;

        let tableOptions: TableOptions = new TableOptions(this.orderByCol);
        tableOptions.filter = this.filter;
        tableOptions.orderByAsc = this.orderByAsc;
        tableOptions.activeColumn = this.activeColumn;
        tableOptions.pageOptions = pageOptions;

        this.changed.emit(
            tableOptions
        );
    }

    public ResetPaginationToFirstPage(): void {
        if (this.pagination) this.pagination.goTo(1, false);
    }

    public onButtonClicked(actionOptions: any): void {
        this.buttonClicked.emit(actionOptions);
    }

    public transformToArray(toTransform: any[]): any[] {
        let arr = [];     
        toTransform.forEach(function (item) {
            arr.push(Object.keys(item).map(function(e) {return item[e]}));
        })
        return arr;
    }

    public updateColumns(columns: ColumnOptions[]) {
        this.columns = columns;
    }
}